#ifndef _JT808_H_
#define _JT808_H_

/*
 ***
 协议应采用大端模式的网络字节序来传递字和双字,字节(BYTE)的传输,按照字节流的方式传输,字(WORD)的传输,先传递高八位,再传递低八位
 ***
 标识位+消息头+消息体+校验码+标识位
 标识位应采用 0x7e 表示,若校验码、消息头以及消息体中出现 0x7e及 0x7d,则要进行转义处理。转义规则定义如下:
 先对 0x7d 进行转义,转换为固定两字节数据:0x7d 0x01:
 再对 0x7e 进行转义,转换为固定两字节数据:0x7d 0x02.
 转义处理过程如下:
 发送消息时:先对消息进行封装,然后计算并填充校验码,最后进行转义处理接收消息时:先对消息进行转义还原处理,然后验证校验码,最后解析消息。
 示例:发送一包内容为 0x30 0x7e 0x08 0x7d 0x55 的数据包,则经过封装如下:0x7e 0x30 0x7d 0x02 0x08 0x7d 0x010x55 0x7e
 */

// 车辆在发生报警时应立即上报一条位置信息,并在位置信息中附加报警状态
#define POS_MESSAGE_ID 0x0200

// 8421码,n字节
typedef struct
{
	uint8_t[6];
}JTBcd;

// 根据安装后终端自身的手机号转换。手机号不足位的,则在前补充数字0
typedef struct
{
	uint8_t[10];
}JTTerminalID;

// 车辆编号，8位
typedef struct
{
	uint8_t[8];
}JTVehicleID

// 消息头内容
typedef struct
{
	uint16_t message_id;
	/*  版本标识位的值固定为1
		15   14       13   12 11 10      9 8 7 6 5 4 3 2 1 0
		保留 版本标识 分包 数据加密方式  消息体长度 
		bit10~bit12 为数据加密标识位,当此三位都为0,表示消息体不加密,当第10位为1,表示消息体经过RSA算法加密.
	 */
	uint16_t message_property;
	uint8_t protocol_version;
	JTTerminalID phone;
	uint16_t serial_number;
}JTBody;

typedef struct
{
	/* 
1:超速报警
2:GNSS 模块发生故障报警
7:终端主电源欠压报警
11:摄像头故障报警
16:胎压预警
23:路线偏离报警
29:碰撞侧翻报警
	 */
	uint32_t warnning_flag;
	/*
	   1->0:未定位;1:定位
	   2->0:北纬;1:南纬
	   3->0:东经;1:西经
	   4->0:运营状态;1:停运状态
	   22->0:车辆处于停止状态;1:车辆处于行驶状态
	 */
	uint32_t status;
	// 以度为单位的纬度值乘以10的6次方,精确到百万分之一度
	uint32_t lat;
	// 以度为单位的经度值乘以10的6次方,精确到百万分之一度
	uint32_t lng;
	// 海拔高度,单位为米(m)
	uint16_t alt;
	// 单位为 1/10 公里每小时(1/10km/h)
	uint16_t speed;
	// 0~359,正北为0,顺时针
	uint16_t orientation;
	// YY-MM-DD-hh-mm-ss(GMT+8 时间,本标准中之后涉及的时间均采用此时区) BCD[6]
	JTBcd bcd;
}JTPOS;

typedef struct
{
	// 基础信息
	JTPOS pos;
	// 车辆编号{BDC[8]}
	JTVehicleID vid;
	// 0~359,正北为0,顺时针,保留两位有效精度(230.34963 - > 23034)
	uint16_t heading;
	// 位姿(-90°到90°，-π/2到π/2),保留两位有效数字(23.08°->2308)
	int16_t yaw;
	int16_t roll;
	int16_t pitch;
	// 转速
	int32_t lrpm;
	int32_t rrpm;
	// SOC,电量百分比，保留两位有效数字(100->1000)
	uint16_t soc;
	// 运行模式
	uint8_t mode;
	// 系统错误编码
	uint16_t errno;
	// 得分(匹配率)
	uint8_t score;
	// 单位米,保留两位有效数字(456039.985,45603998)
	int32_t rtk_x;
	int32_t rtk_y;
	int32_t rtk_z;
	// 融合定位,保留两位有效数字(456039.985,45603998)
	int32_t mix_x;	
	int32_t mix_y;	
	int32_t mix_z;	
}JTPOSEXTEN;


uint16_t calculateCheckSum(const uint8_t* data, size_t length) {  
	uint16_t checksum = 0;  
	for (size_t i = 0; i < length; ++i) {  
		checksum += data[i];  
	}  
	return checksum;  
}  

#endif
